// This is the View
// Its only job is to display what the user sees
// It performs no calculations, but instead passes
// information entered by the user to whomever needs
// it.

package pt.iscte.dcti.pa.view;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Observable;
import java.util.Observer;

import javax.swing.*;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.TableEditor;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;

import controller.WorksheetController;

public class WorksheetView extends JFrame {

	private DynamicTable dynamicTable;
	
	private Display display;
	private final Shell shell;
	
	VisibleElement[][] matriz;

	
	public WorksheetView(int _numRows, int _numColumns) {

		//ctrl = new Control();
		display = new Display();
		shell = new Shell(display);
		shell.setLayout(new RowLayout(SWT.HORIZONTAL));

		dynamicTable = new DynamicTable(shell);

		setMatriz(_numRows, _numColumns);
		
		dynamicTable.load(matriz);

		setTableEditor(dynamicTable.getTable());
		
	}
	
	public void setCellText(int abscisa, int ordinate, String value) {
		
		dynamicTable.getTable().getItem(abscisa).setText(ordinate, value);
	
	}
	
	public VisibleElement[][] getMatriz()
	{
		return this.matriz;
	}
	
	
	
	public void addObserver(java.util.Observer theObserver) {
		for (VisibleElement[] linha : matriz) {
			for (VisibleElement visibleElement : linha) {
				visibleElement.addObserver(theObserver);				
			}
		}
	}
	
	public void showTable(){
		
		shell.pack();
		shell.open();
		
		if (shell != null && display != null) {
			while (!shell.isDisposed()) {
				if (!display.readAndDispatch())
					display.sleep();
			}
			display.dispose();
		}
		
		inspectSheet();
	}

	public void addListener(final Table table, final TableEditor editor) {

		table.addListener(SWT.MouseDown, new Listener() { // para o evento MouseDown

					public void handleEvent(Event event) {
						Rectangle clientArea = table.getClientArea();
						Point pt = new Point(event.x, event.y);

						int index = table.getTopIndex();
						while (index < table.getItemCount()) { // para cada linha
							boolean visible = false;
							final TableItem item = table.getItem(index);

							for (int i = 0; i < table.getColumnCount(); i++) { // para  cada célula de cada linha

								Rectangle rect = item.getBounds(i);
								if (rect.contains(pt)) {
									final int column = i;
									final Text textBox = new Text(table, SWT.NONE); // para a textbox

									Listener textListener = getListener(item, index, column, textBox);

									textBox.addListener(SWT.FocusIn, textListener);
									textBox.addListener(SWT.FocusOut, textListener);
									//textBox.addListener(SWT.Traverse, textListener);

									editor.setEditor(textBox, item, i);
									textBox.setText(item.getText(i));

									textBox.selectAll();
									textBox.setFocus();
									return;
								}
								if (!visible && rect.intersects(clientArea)) {
									visible = true;
								}
							}
							if (!visible)
								return;
							index++;
						}
					}
				});
	}
	
	private void setTableEditor(Table table) {
		final TableEditor editor = new TableEditor(table);
		editor.horizontalAlignment = SWT.LEFT;
		editor.grabHorizontal = true;

		addListener(table, editor);
	}
	
	private void setMatriz(int numRows, int numColumns) {
		matriz = new VisibleElement[numRows][numColumns];
		
		for (int i = 0; i < numRows; i++) {
			for (int j = 0; j < numColumns; j++) {
				matriz[i][j] = new VisibleElement(i, j, this);
			}
		}
	}
	
	//cada célula leva um listener
	private Listener getListener(final TableItem item, final int itemIndex, final int columnIndex, final Text textBox) {
		return new Listener() {
			public void handleEvent(final Event e) {

				switch (e.type) {
				case SWT.FocusIn:
					//getFormula(itemIndex, columnIndex);
					break;
				
				case SWT.FocusOut:
					setValue(item, itemIndex, columnIndex, textBox);
					textBox.dispose();
					break;
				case SWT.Traverse:
					switch (e.detail) {
					case SWT.TRAVERSE_TAB_NEXT:
					case SWT.TRAVERSE_RETURN:
						setValue(item, itemIndex, columnIndex, textBox);
						// FALL THROUGH
					case SWT.TRAVERSE_ESCAPE:
						textBox.dispose();
						e.doit = false;
					}
					break;
				}
			}
		};
	}
	
	/*
	private void getFormula(int abscissa, int ordinate) {
		matriz[abscissa][ordinate].fireObserver();
	}
	*/
	private void setValue(final TableItem item, int rowItemIndex, final int columnIndex, final Text textBox) {
		
		String textValue = textBox.getText();
		item.setText(columnIndex, textValue);
		
		if (textValue != null && !textValue.isEmpty()) {
			matriz[rowItemIndex][columnIndex].setValue(textValue);
		}						
	}
	
	//imprime a folha de calculo
	private void inspectSheet() {		
		for (VisibleElement[] linha : matriz) {
			for (VisibleElement celula : linha) {
				System.out.println((celula != null ? celula.getValue() : " ") + "|");
			}
			System.out.println();
		}
	}
}
